//<<<+++OPENSOURCE
//<<<+++OPENSOURCE_LICENSE
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT||LIC==GOOGLE

/**
 * @addtogroup FXCRT
 * @{
 */

/**
 * @file
 * @brief Strings, variable-length sequence of characters.
 *
 * There are two strings here, byte-string and wide-string.
 */

//<<<+++OPENSOURCE_MUST_BEGIN
#ifndef _FX_STRING_H_
#define _FX_STRING_H_
//<<<+++OPENSOURCE_MUST_END

class CFX_ByteStringC;
class CFX_ByteString;
class CFX_WideStringC;
class CFX_WideString;
struct CFX_CharMap;
class CFX_BinaryBuf;

/** @brief String size is limited to 2^31-1. */
typedef int FX_STRSIZE;

class CFX_ByteStringL;
class CFX_WideStringL;

//*****************************************************************************
//* CFX_ByteStringC - constant byte string
//*****************************************************************************
/**
 * @brief CONSTANT BYTE STRING CLASS
 *
 * Constant byte string, it contains no buffer so its content can't be changed directly.
 */
class CFX_ByteStringC : public CFX_Object
{
public:
	/**
	 * Constructs a null constant string.
	 */
	CFX_ByteStringC()
	{
		m_Ptr = NULL;
		m_Length = 0;
	}
	/**
	 * Constructs from a byte string.
	 *
	 * @param[in] ptr	Pointer to a constant byte string.
	 * @param[in] size	The length of the byte string.
	 */
	CFX_ByteStringC(FX_LPCBYTE ptr, FX_STRSIZE size)
	{
		m_Ptr = ptr;
		m_Length = size;
	}
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifndef _NO_LPCSTR_SUPPORT_
//<<<+++OPENSOURCE_MUST_END
	/**
	 * Construct from a character string.
	 *
	 * @param[in] ptr	Pointer to a constant character string, the string must be null-terminated.
	 */
	CFX_ByteStringC(FX_LPCSTR ptr)
	{
		m_Ptr = (FX_LPCBYTE)ptr;
		m_Length = ptr ? (FX_STRSIZE)FXSYS_strlen(ptr) : 0;
	}
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#endif
//<<<+++OPENSOURCE_MUST_END
	/**
	 * Construct from a single character.
	 *
	 * @param[in] ch	A single character.
	 */
	CFX_ByteStringC(FX_CHAR& ch)
	{
		m_Ptr = (FX_LPCBYTE)&ch;
		m_Length = 1;
	}
	/**
	 * Construct from a character string.
	 *
	 * len can be -1 for null-terminated string.
	 * @param[in] ptr	Pointer to a constant character string.
	 * @param[in] len	The length of the character string. 
	 */
	CFX_ByteStringC(FX_LPCSTR ptr, FX_STRSIZE len)
	{
		m_Ptr = (FX_LPCBYTE)ptr;
		if (len == -1)
			m_Length = (FX_STRSIZE)FXSYS_strlen(ptr);
		else
			m_Length = len;
	}
	/**
	 * Copy constructor
	 * 
	 * @param[in] src	constant ref to a CFX_ByteStringC object.
	 */
	CFX_ByteStringC(const CFX_ByteStringC& src)
	{
		m_Ptr = src.m_Ptr;
		m_Length = src.m_Length;
	}
	/**
	 * Construct from a byte string.
	 * 
	 * @param[in] src	constant ref to a CFX_ByteString object.
	 */
	CFX_ByteStringC(const CFX_ByteString& src);

	/**
	 * assignment(=) operator overload. From a character string.
	 *
	 * @param[in] src	Pointer to a constant character string.
	 */
	CFX_ByteStringC& operator = (FX_LPCSTR src)
	{
		m_Ptr = (FX_LPCBYTE)src;
		m_Length = (FX_STRSIZE)FXSYS_strlen(src);
		return *this;
	}
	/**
	 * assignment(=) operator overload. From a CFX_ByteStringC object.
	 *
	 * @param[in] src	constant ref to a CFX_ByteStringC object.
	 */
	CFX_ByteStringC& operator = (const CFX_ByteStringC& src)
	{
		m_Ptr = src.m_Ptr;
		m_Length = src.m_Length;
		return *this;
	}
	/**
	 * assignment(=) operator overload. From a CFX_ByteString object.
	 *
	 * @param[in] src	constant ref to a CFX_ByteString object.
	 */
	CFX_ByteStringC& operator = (const CFX_ByteString& src);

	/**
	 * comparison(==) operator overload. case-sensitive.
	 *
	 * @param[in] str	constant ref to a CFX_ByteStringC object.
	 * @return true means equal, otherwise not equal.
	 */
	bool			operator == (const CFX_ByteStringC& str) const
	{
		return 	str.m_Length == m_Length && FXSYS_memcmp32(str.m_Ptr, m_Ptr, m_Length) == 0;
	}
	/**
	 * comparison(!=) operator overload. case-sensitive.
	 *
	 * @param[in] str	constant ref to a CFX_ByteStringC object.
	 * @return true means not equal, otherwise equal.
	 */
	bool			operator != (const CFX_ByteStringC& str) const
	{
		return 	str.m_Length != m_Length || FXSYS_memcmp32(str.m_Ptr, m_Ptr, m_Length) != 0;
	}

/** @brief Construct a ID from four integer values. */
#define FXBSTR_ID(c1, c2, c3, c4) ((c1 << 24) | (c2 << 16) | (c3 << 8) | (c4))

	/**
	 * Get a DWORD identifier of the string, from a particular position.
	 *
	 * This DWORD can be used for quick comparison. Using MSB-first scheme.
	 * If the string doesn't have enough bytes, then zero will be used missing bytes.
	 *
	 * @param[in] start_pos	Start position in the constant byte string.
	 * @return A DWORD identifier.
	 *
	 * For example:
	 * @code
	 *		CFX_ByteString str1("hello"), str2("hey");
	 *		FX_BOOL bCheck1 = str1.GetID() == FXBSTR_ID('h', 'e', 'l', 'l');	// returns TRUE
	 *		FX_BOOL bCheck2 = str2.GetID() == FXBSTR_ID('h', 'e', 'y', 0);	// returns TRUE
	 * @endcode
	 */
	FX_DWORD		GetID(FX_STRSIZE start_pos = 0) const;

	/**
	 * Returns a constant byte string pointer to the byte string.
	 *
	 * @return A constant byte string pointer to the byte string.
	 */
	FX_LPCBYTE		GetPtr() const { return m_Ptr; }
	/**
	 * Returns a constant character string pointer to the byte string.
	 *
	 * @return a constant character string pointer to the byte string.
	 */
	FX_LPCSTR		GetCStr() const { return (FX_LPCSTR)m_Ptr; }
	/**
	 * Returns The length of the byte string.
	 *
	 * @return The length of the byte string.
	 */
	FX_STRSIZE		GetLength() const { return m_Length; }
	/**
	 * This method determines whether a CFX_ByteStringC object is empty.
	 *
	 * @return true means empty, otherwise not empty.
	 */
	bool			IsEmpty() const { return m_Length == 0; }

	/**
	 * This casting operator accesses the byte string referred in a CFX_ByteStringC object.
	 *
	 * @return Returns a byte string pointer to the data in the string.
	 * 
	 * @note
	 * A CFX_ByteStringC can't be implicitly converted to a FX_LPCSTR pointer,
	 * because very likely the CFX_ByteStringC buffer is not null-terminated.
	 */
	operator		FX_LPCBYTE() const { return m_Ptr; }

	/**
	 * This method retrieves a single byte specified by an index number.
	 *
	 * @param[in] index		Specifies the zero-based index in the byte string.
	 * @return A single byte.
	 */
	FX_BYTE			GetAt(FX_STRSIZE index) const { return m_Ptr[index]; }

	/**
	 * This method extracts a substring of length count bytes from this CFX_ByteStringC object,
	 * starting at position index (zero-based).
	 *
	 * @param[in] index		Specifies the zero-based index in the CFX_ByteStringC object.
	 * @param[in] count		Specifies the number of bytes to extract from this CFX_ByteStringC object.
	 * @return A CFX_ByteStringC object refer to the substring.
	 */
	CFX_ByteStringC	Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const
	{
		if (index < 0) index = 0;
		if (index > m_Length) return CFX_ByteStringC();
		if (count < 0 || count > m_Length - index) count = m_Length - index;
		return CFX_ByteStringC(m_Ptr + index, count);
	}

protected:
	/** The constant byte string pointer. */
	FX_LPCBYTE		m_Ptr;
	/** the length in bytes of the byte string. */
	FX_STRSIZE		m_Length;

private:
	/**
	 * new operator forbidden. Cannot allocate a CFX_ByteStringC in heap.
	 */
	void*			operator new (size_t) throw() { return NULL; }
};

/** @brief A ref to a constant CFX_ByteStringC object. */
typedef const CFX_ByteStringC& FX_BSTR;

/**
 * @brief All application should use the following macro when specifying a string constant.
 * "str" must be a character string constant.
 *
 * For example:
 * @code
 *		FX_BSTRC("abc").
 * @endcode
 */
#define FX_BSTRC(str) CFX_ByteStringC(str, sizeof str-1)

//*****************************************************************************
//* CFX_ByteString - byte string
//*****************************************************************************
/** @brief This class represents the data of a byte string object. */
struct CFX_StringData
{
	/** reference count. */
	long		m_nRefs;
	/** length of data (excluding terminator). */
	FX_STRSIZE	m_nDataLength;
	/** length of allocation. */
	FX_STRSIZE	m_nAllocLength;
	/** real data (actually a variable-sized array). */
	FX_CHAR		m_String[1];
};

/**
 * @brief BYTE STRING CLASS
 */
class CFX_ByteString : public CFX_Object
{
public:
	/**
	 * Construct a null byte string.
	 */
	CFX_ByteString() { m_pData = NULL; }
	/**
	 * Copy constructor.
	 *
	 * @param[in] str	A constant ref to a CFX_ByteString object.
	 */
	CFX_ByteString(const CFX_ByteString& str);
	/**
	 * Construct from a single character.
	 *
	 * @param[in] ch	A single character.
	 */
	CFX_ByteString(char ch);
	/**
	 * Construct from a character string.
	 *
	 * @param[in] ptr	Pointer to a constant character string.
	 * @param[in] len	The length of the character string. len can be -1 for zero terminated string.
	 */
	CFX_ByteString(FX_LPCSTR ptr, FX_STRSIZE len=-1);
	/**
	 * Construct from a byte string.
	 *
	 * @param[in] ptr	Pointer to a constant byte string.
	 * @param[in] len	The length of the byte string.
	 */
	CFX_ByteString(FX_LPCBYTE ptr, FX_STRSIZE len);
	/**
	 * Construct from a constant ref to a CFX_ByteStringC object.
	 *
	 * @param[in] bstrc		A constant ref to a CFX_ByteStringC object.
	 */
	CFX_ByteString(FX_BSTR bstrc);
	/**
	 * Concatenate constructor.
	 *
	 * @param[in] bstrc1	Fist constant ref to a CFX_ByteStringC object.
	 * @param[in] bstrc2	Second constant ref to a CFX_ByteStringC object.
	 */
	CFX_ByteString(FX_BSTR bstrc1, FX_BSTR bstrc2);
	/**
	 * Destructor.
	 */
	~CFX_ByteString();

	/**
	 * Create a CFX_ByteString object from a Unicode string. Convert from Unicode to system multi-byte charset.
	 *
	 * @param[in] ptr	Pointer to a constant Unicode string.
	 * @param[in] len	The length of the Unicode string. len can be -1 for zero terminated Unicode string.
	 * @return A byte string.
	 */
	static CFX_ByteString	FromUnicode(FX_LPCWSTR ptr, FX_STRSIZE len = -1);
	/**
	 * Create a CFX_ByteString object from a CFX_WideString object.
	 *
	 * @param[in] str	A ref to a constant CFX_WideString object.
	 * @return A byte string.
	 */
	static CFX_ByteString	FromUnicode(const CFX_WideString& str);

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * Create a CFX_ByteString object from a native _wchar_t string.
	 *
	 * @param[in] str	Pointer to a constant _wchar_t string.
	 * @param[in] len	The length of the _wchar_t string. len can be -1 for zero terminated _wchar_t string.
	 * @return A byte string.
	 */
	static CFX_ByteString	FromUnicode(const wchar_t* str, FX_STRSIZE len = -1) { return FromUnicode((FX_LPCWSTR)str, len); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * FX_LPCSTR type conversion operator. CFX_ByteString can be used in places where FX_LPCSTR or FX_LPCBYTE is needed.
	 */
	operator				FX_LPCSTR() const { return m_pData ? m_pData->m_String : ""; }
	/**
	 * FX_LPCBYTE type conversion operator. CFX_ByteString can be used in places where FX_LPCSTR or FX_LPCBYTE is needed.
	 */
	operator				FX_LPCBYTE() const { return m_pData ? (FX_LPCBYTE)m_pData->m_String : NULL; }

	/**
	 * Get number of bytes in the byte string (not counting any possible terminator).
	 *
	 * @return The Length of the byte string.
	 */
	FX_STRSIZE				GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; }

	/**
	 * This method determines whether a CFX_ByteString object is empty.
	 *
	 * @return true means empty, otherwise not empty.
	 */
	bool					IsEmpty() const { return !GetLength(); }

	/**
	 * Compare the the string with another. case-sensitive.
	 * 
	 * Return -1 if this string is "smaller" (in alphabetic order) than the other,
	 * 0 for equal, 1 for larger in alphabetic order.
	 *
	 * @param[in] str		The byte string to be compared.
	 * @retval -1	smaller
	 * @retval 0	equal
	 * @retval 1	larger
	 */
	int						Compare(FX_BSTR str) const;
	
	/**
	 * Check if this string equals to another. It's faster than Compare if you just want to check
	 * whether two strings equal.
	 *
	 * @param[in] str	The byte string to be compared.
	 * @return true means equal, otherwise not equal.
	 */
	bool					Equal(FX_BSTR str) const;
	
	/**
	 * Check if two string equal not considering case. It means letters 'A'-'Z' will be considered
	 * same as 'a'-'z'.
	 *
	 * @param[in] str	The byte string to be compared.
	 * @return true means equal, otherwise not equal.
	 */
	bool					EqualNoCase(FX_BSTR str) const;

//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifndef _NO_LPCSTR_SUPPORT_
//<<<+++OPENSOURCE_MUST_END
	/**
	 * comparison(==) operator overload. case-sensitive.
	 *
	 * @param[in] str	The null-terminated character string to be compared.
	 * @return true means equal, otherwise not equal.
	 */
	bool					operator == (FX_LPCSTR str) const { return Equal(str); }
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#endif
//<<<+++OPENSOURCE_MUST_END
	/**
	 * comparison(==) operator overload. case-sensitive.
	 *
	 * @param[in] str	The null-terminated constant byte string to be compared.
	 * @return true means equal, otherwise not equal.
	 */
	bool					operator == (FX_BSTR str) const { return Equal(str); }
	/**
	 * comparison(==) operator overload. case-sensitive.
	 *
	 * @param[in] str	The null-terminated byte string to be compared.
	 * @return true means equal, otherwise not equal.
	 */
	bool					operator == (const CFX_ByteString& str) const;
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifndef _NO_LPCSTR_SUPPORT_
//<<<+++OPENSOURCE_MUST_END
	/**
	 * comparison(!=) operator overload. case-sensitive.
	 *
	 * @param[in] str	The null-terminated character string to be compared.
	 * @return true means not equal, otherwise equal.
	 */
	bool					operator != (FX_LPCSTR str) const { return !Equal(str); }
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#endif
//<<<+++OPENSOURCE_MUST_END
	/**
	 * comparison(!=) operator overload. case-sensitive.
	 *
	 * @param[in] str	The null-terminated constant byte string to be compared.
	 * @return true means not equal, otherwise equal.
	 */
	bool					operator != (FX_BSTR str) const { return !Equal(str); }
	/**
	 * comparison(!=) operator overload. case-sensitive.
	 *
	 * @param[in] str	The null-terminated byte string to be compared.
	 * @return true means not equal, otherwise equal.
	 */
	bool					operator != (const CFX_ByteString& str) const { return !operator==(str); }

	/**
	 * Set this string to be empty.
	 */
	void					Empty();

	/**
	 * assignment(=) operator overload. From a character string.
	 *
	 * @param[in] str	A pointer to a constant character string.
	 */
	const CFX_ByteString&	operator = (FX_LPCSTR str);
	/**
	 * assignment(=) operator overload. From a constant byte string.
	 *
	 * @param[in] bstrc A ref to a constant byte string.
	 */
	const CFX_ByteString&	operator = (FX_BSTR bstrc);
	/**
	 * assignment(=) operator overload. From a CFX_ByteString object.
	 *
	 * @param[in] stringSrc		A ref to a constant CFX_ByteString object.
	 */
	const CFX_ByteString&	operator = (const CFX_ByteString& stringSrc);
	/**
	 * assignment(=) operator overload. From a CFX_BinaryBuf object.
	 *
	 * @param[in] buf			A ref to a constant CFX_BinaryBuf object.
	 */
	const CFX_ByteString&	operator = (const CFX_BinaryBuf& buf);

	/**
	 * Load from a byte string.
	 *
	 * @param[in] str	Pointer to a constant byte string.
	 * @param[in] len	The length of the byte string.
	 */
	void					Load(FX_LPCBYTE str, FX_STRSIZE len);

	/**
	 * Concatenation(+=) operator overload. Concatenate a single character. 
	 *
	 * @param[in] ch	A single character.
	 */
	const CFX_ByteString&	operator += (FX_CHAR ch);
	/**
	 * Concatenation(+=) operator overload. Concatenate a null-terminated character string.
	 *
	 * @param[in] str	Pointer to a constant null-terminated character string.
	 */
	const CFX_ByteString&	operator += (FX_LPCSTR str);
	/**
	 * Concatenation(+=) operator overload. Concatenate a CFX_ByteString object.
	 *
	 * @param[in] str	A ref to a constant CFX_ByteString object.
	 */
	const CFX_ByteString&	operator += (const CFX_ByteString& str);
	/**
	 * Concatenation(+=) operator overload. Concatenate a constant CFX_ByteStringC object.
	 *
	 * @param[in] bstrc	A ref to a constant CFX_ByteStringC object.
	 */
	const CFX_ByteString&	operator += (FX_BSTR bstrc);

	/**
	 * This method retrieves a single byte specified by an index number.
	 *
	 * @param[in] nIndex	Specifies the zero-based index in the byte string.
	 * @return A single byte.
	 */
	FX_BYTE					GetAt(FX_STRSIZE nIndex) const { return m_pData ? m_pData->m_String[nIndex] : 0; }
	/**
	 * Subscript([]) operator overload. It retrieves a single byte specified by the zero-based index in nIndex.
	 *
	 * @param[in] nIndex	Specifies the zero-based index in the byte string.
	 * @return A single byte.
	 */
	FX_BYTE					operator[](FX_STRSIZE nIndex) const { return m_pData ? m_pData->m_String[nIndex] : 0; }
	/**
	 * This method overwrites a single byte specified by an index number.
	 *
	 * @param[in] nIndex	Specifies the zero-based index in the byte string.
	 * @param[in] ch		a single character.
	 */
	void					SetAt(FX_STRSIZE nIndex, FX_CHAR ch);

	/**
	 * Insert a character before specific position.
	 *
	 * @param[in] index		Specifies the zero-based index in the byte string.
	 * @param[in] ch		A single character.
	 * @return The new length of the byte string.
	 */
	FX_STRSIZE				Insert(FX_STRSIZE index, FX_CHAR ch);

	/**
	 * Delete one or more characters starting from specific position.
	 * 
	 * @param[in] index		Specifies the zero-based index in the byte string for starting deleting.
	 * @param[in] count		Count of bytes to be deleted.
	 * @return The new length of the byte string.
	 */
	FX_STRSIZE				Delete(FX_STRSIZE index, FX_STRSIZE count = 1);
	
	/**
	 * Format a number of parameters into this byte string.
	 * 
	 * On desktop platforms, this function supports all the sprintf() formats.
	 * On embedded platforms, it supports only a subset of formats:
	 * - Supported types: d, u, f, g, x, X, s, c, %.
	 * - Width field supported;
	 * - Precision not supported;
	 * - Flags supported: '0';
	 * 
	 * @param[in] lpszFormat	Specifies a format-control string.
	 */
	void					Format(FX_LPCSTR lpszFormat, ... );
	/**
	 * Format a number of parameters into this byte string. using va_list.
	 *
	 * @param[in] lpszFormat	Specifies a format-control string.
	 * @param[in] argList		Variable-argument lists.
	 * @see CFX_ByteString::Format
	 */
	void					FormatV(FX_LPCSTR lpszFormat, va_list argList);
	
	/**
	 * Reserve a buffer that can hold specific number of bytes.
	 * 
	 * The content of this string won't be changed.
	 * This can be used if application anticipates the string may grow many times, in this case,
	 * reserving a larger buffer will support string growth without buffer reallocation.
	 *
	 * @param[in] len		the Length expected to reserve.
	 */
	void					Reserve(FX_STRSIZE len);

	/**
	 * Get a buffer with specific number of bytes allocated.
	 *
	 * The content of this string won't be affected by GetBuffer() function.
	 * Caller can modified the returned buffer, and should call ReleaseBuffer() after modification done.
	 * 
	 * @param[in] len		the Length expected to get.
	 * @return A character string pointer to the byte string.
	 */
	FX_LPSTR				GetBuffer(FX_STRSIZE len);

	/**
	 * Lock and get the current string buffer, so the caller can modify the returned buffer.
	 * Caller can modified the returned buffer, and should call ReleaseBuffer() after modification done.
	 *
	 * @return A character string pointer to the byte string.
	 */
	FX_LPSTR				LockBuffer();

	/**
	 * Release the buffer fetched by GetBuffer() or LockBuffer, and set the length of modified string.
	 *
	 * If len parameter is -1, then it's assumed to be a zero-terminated string.
	 *
	 * @param[in] len		the Length expected to release to.
	 */
	void					ReleaseBuffer(FX_STRSIZE len = -1);

	/**
	 * This method extracts a substring from this CFX_ByteString object,
	 * starting at position nFirst (zero-based) to last. 
	 *
	 * @param[in] first		Specifies the zero-based index of the starting position in this CFX_ByteString object.
	 * @return A CFX_ByteString sub-string.
	 */
	CFX_ByteString			Mid(FX_STRSIZE first) const;
	/**
	 * This method extracts a substring of count bytes from this CFX_ByteString object,
	 * starting at position nFirst (zero-based) to last. 
	 *
	 * @param[in] first		Specifies the zero-based index of the starting position in this CFX_ByteString object.
	 * @param[in] count		The count of bytes expected to extract for the sub-string.
	 * @return A CFX_ByteString sub-string.
	 */
	CFX_ByteString			Mid(FX_STRSIZE first, FX_STRSIZE count) const;
	/**
	 * This method extracts the first (leftmost) count bytes from this CFX_ByteString object as a sub-string. 
	 *
	 * @param[in] count		The count of bytes expected to extract for the sub-string.
	 * @return A CFX_ByteString sub-string.
	 */
	CFX_ByteString			Left(FX_STRSIZE count) const;
	/**
	 * This method extracts the last (rightmost) count bytes from this CFX_ByteString object as a sub-string. 
	 *
	 * @param[in] count		The count of bytes expected to extract for the sub-string.
	 * @return A CFX_ByteString sub-string.
	 */
	CFX_ByteString			Right(FX_STRSIZE count) const;

	/**
	 * Find a sub-string, from specific position. Only first occurrence is found.
	 *
	 * @param[in] lpszSub	The sub-string to be found.
	 * @param[in] start		Specifies the zero-based index of the starting position to do finding.
	 * @retval -1 Not found.
	 * @retval other Specifies position in the string.
	 */
	FX_STRSIZE				Find(FX_BSTR lpszSub, FX_STRSIZE start=0) const;
	/**
	 * Find a character, from specific position. Only first occurrence is found.
	 *
	 * @param[in] ch		The character to be found.
	 * @param[in] start		Specifies the zero-based index of the starting position to do finding.
	 * @retval -1 Not found.
	 * @retval other Specifies position in the string.
	 */
	FX_STRSIZE				Find(FX_CHAR ch, FX_STRSIZE start=0) const;
	/**
	 * Find a character from end of the string
	 *
	 * @retval -1 Not found.
	 * @retval other Specifies position in the string.
	 */
	FX_STRSIZE				ReverseFind(FX_CHAR ch) const;

	/**
	 * Change case of English letters to lower.
	 */
	void					MakeLower();
	/**
	 * Change case of English letters to upper.
	 */
	void					MakeUpper();

	/**
	 * Trim white spaces from the right side of the byte string.
	 */
	void					TrimRight();
	/**
	 * Trim continuous occurrences of specified character from right side of the byte string.
	 * 
	 * @param[in] chTarget		The specified character.
	 */
	void					TrimRight(FX_CHAR chTarget);
	/**
	 * Trim continuous occurrences of specified characters from right side of the byte string.
	 *
	 * @param[in] lpszTargets	The specified characters.
	 */
	void					TrimRight(FX_BSTR lpszTargets);
	/**
	 * Trim white spaces from the left side of the byte string.
	 */
	void					TrimLeft();
	/**
	 * Trim continuous occurrences of specified characters from left side of the byte string.
	 * 
	 * @param[in] chTarget		The specified character.
	 */
	void					TrimLeft(FX_CHAR chTarget);
	/**
	 * Trim continuous occurrences of specified characters from left side of the byte string.
	 *
	 * @param[in] lpszTargets	The specified characters.
	 */
	void					TrimLeft(FX_BSTR lpszTargets);

	/**
	 * Replace all patterns in the string with a new sub-string.
	 *
	 * @param[in] lpszOld		Specified the string to be matched and replaced in the byte string.
	 * @param[in] lpszNew		Specified the string to replace.
	 * @return The number of replaced patterns.
	 */
	FX_STRSIZE				Replace(FX_BSTR lpszOld, FX_BSTR lpszNew);

	/**
	 * Remove all occurrence of a particular character.
	 * 
	 * @param[in] ch	Specified the character to be removed.
	 * @return The number of characters removed.
	 */
	FX_STRSIZE				Remove(FX_CHAR ch);

	/**
	 * Decode a UTF-8 unicode string (assume this byte string is UTF-8 encoded).
	 *
	 * @return A unicode string.
	 */
	CFX_WideString			UTF8Decode() const;

	/**
	 * Load unicode data into this byte string, using specified character mapper.
	 * If no character mapper specified, the system default mapper will be used.
	 *
	 * @param[in] str		The input unicode string.
	 * @param[in] pCharMap	Specified character mapper to be used for converting.
	 */
	void					ConvertFrom(const CFX_WideString& str, CFX_CharMap* pCharMap = NULL);

	/**
	 * Get a DWORD identifier of the string. See CFX_ByteStringC::GetID() for details.
	 *
	 * @param[in] start_pos		Start position in the constant byte string.
	 * @return A FX_DWORD identifier.
	 */
	FX_DWORD				GetID(FX_STRSIZE start_pos = 0) const;

	/**
	 * Load the whole content of a file.
	 * 
	 * @param[in] file_path		The file path.
	 * @return a CFX_ByteString object.
	 */
	static CFX_ByteString	LoadFromFile(FX_BSTR file_path);

/** @brief For formating integer: the value is signed. */
#define FXFORMAT_SIGNED			1
/** @brief For formating integer: using hexadecimal  format */
#define FXFORMAT_HEX			2		
/** @brief For formating integer: using with FXFORMAT_HEX to produce capital hexadecimal letters */
#define FXFORMAT_CAPITAL		4

	/**
	 * Convert from Integer.
	 *
	 * The flags can be following flags (single or compound):
	 * - FXFORMAT_SIGNED 
	 * - FXFORMAT_HEX
	 * - FXFORMAT_CAPITAL
	 *
	 * @see FXFORMAT_SIGNED FXFORMAT_HEX FXFORMAT_CAPITAL
	 * 
	 * @param[in] i			The input integer.
	 * @param[in] flags		The formating flags.
	 * @return A CFX_ByteString object.
	 */
	static CFX_ByteString	FormatInteger(int i, FX_DWORD flags = 0);
	/**
	 * Convert from floating-point number.
	 *
	 * @param[in] f				The input floating-point number.
	 * @param[in] precision		The number of decimal digits. Not used.
	 * @return A CFX_ByteString object.
	 *
	 * @todo We need a better algorithm and to support precision. 
	 */
	static CFX_ByteString	FormatFloat(FX_FLOAT f, int precision = 0);

protected:
	/** Pointer to ref counted byte string data. */
	struct CFX_StringData*	m_pData;

	void					AllocCopy(CFX_ByteString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex, FX_STRSIZE nExtraLen) const;
	void					AssignCopy(FX_STRSIZE nSrcLen, FX_LPCSTR lpszSrcData);
	void					ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCSTR lpszSrc1Data, FX_STRSIZE nSrc2Len, FX_LPCSTR lpszSrc2Data);
	void					ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCSTR lpszSrcData);
	void					CopyBeforeWrite();
	void					AllocBeforeWrite(FX_STRSIZE nLen);
};

inline CFX_ByteStringC::CFX_ByteStringC(const CFX_ByteString& src)
{
	m_Ptr = (FX_LPCBYTE)src;
	m_Length = src.GetLength();
}

inline CFX_ByteStringC& CFX_ByteStringC::operator = (const CFX_ByteString& src)
{
	m_Ptr = (FX_LPCBYTE)src;
	m_Length = src.GetLength();
	return *this;
}

/**
 * @name Byte string concatenation operation
 * Both side of the concatenation operator (+) can be:
 * - A buffered byte string (const CFX_ByteString&);
 * - A non-buffered byte string (const CFX_ByteStringC&, a.k.a FX_BSTR);
 * - A zero-terminated C-style string (FX_LPCSTR);
 * - A single character or byte (FX_CHAR);
 */
 /*@{*/

/**
 * Concatenate a non-buffered byte string and a non-buffered byte string.
 *
 * @param[in] str1		A non-buffered byte string.
 * @param[in] str2		A non-buffered byte string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (FX_BSTR str1, FX_BSTR str2) { return CFX_ByteString(str1, str2); }
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifndef _NO_LPCSTR_SUPPORT_
//<<<+++OPENSOURCE_MUST_END
/**
 * Concatenate a non-buffered byte string and a zero-terminated C-style string
 *
 * @param[in] str1		A non-buffered byte string.
 * @param[in] str2		A zero-terminated C-style string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (FX_BSTR str1, FX_LPCSTR str2) { return CFX_ByteString(str1, str2); }
/**
 * Concatenate a zero-terminated C-style string and a non-buffered byte string. 
 *
 * @param[in] str1		A zero-terminated C-style string.
 * @param[in] str2		A non-buffered byte string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (FX_LPCSTR str1,FX_BSTR str2) { return CFX_ByteString(str1, str2); }
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#endif
//<<<+++OPENSOURCE_MUST_END
/**
 * Concatenate a non-buffered byte string and a single character or byte. 
 *
 * @param[in] str1		A non-buffered byte string.
 * @param[in] ch		A single character or byte.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (FX_BSTR str1, FX_CHAR ch) { return CFX_ByteString(str1, CFX_ByteStringC(ch)); }
/**
 * Concatenate a single character or byte and a non-buffered byte string. 
 *
 * @param[in] ch		A single character or byte.
 * @param[in] str2		A non-buffered byte string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (FX_CHAR ch, FX_BSTR str2) { return CFX_ByteString(ch, str2); }

/**
 * Concatenate a buffered byte string and a buffered byte string. 
 *
 * @param[in] str1		A buffered byte string.
 * @param[in] str2		A buffered byte string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (const CFX_ByteString& str1, const CFX_ByteString& str2) { return CFX_ByteString(str1, str2); }
/**
 * Concatenate a buffered byte string and a single character or byte. 
 *
 * @param[in] str1		A buffered byte string.
 * @param[in] ch		A single character or byte.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (const CFX_ByteString& str1, FX_CHAR ch) { return CFX_ByteString(str1, CFX_ByteStringC(ch)); }
/**
 * Concatenate a single character or byte and a buffered byte string. 
 *
 * @param[in] ch		A single character or byte.
 * @param[in] str2		A buffered byte string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (FX_CHAR ch, const CFX_ByteString& str2) { return CFX_ByteString(ch, str2); }
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifndef _NO_LPCSTR_SUPPORT_
//<<<+++OPENSOURCE_MUST_END
/**
 * Concatenate a buffered byte string and a zero-terminated C-style string. 
 *
 * @param[in] str1		A buffered byte string.
 * @param[in] str2		A zero-terminated C-style string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (const CFX_ByteString& str1, FX_LPCSTR str2) { return CFX_ByteString(str1, str2); }
/**
 * Concatenate a zero-terminated C-style string and a buffered byte string. 
 *
 * @param[in] str1		A zero-terminated C-style string.
 * @param[in] str2		A buffered byte string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (FX_LPCSTR str1, const CFX_ByteString& str2) { return CFX_ByteString(str1, str2); }
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#endif
//<<<+++OPENSOURCE_MUST_END
/**
 * Concatenate a buffered byte string and a non-buffered byte string. 
 *
 * @param[in] str1		A buffered byte string.
 * @param[in] str2		A non-buffered byte string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (const CFX_ByteString& str1, FX_BSTR str2) { return CFX_ByteString(str1, str2); }
/**
 * Concatenate a non-buffered byte string and a buffered byte string. 
 *
 * @param[in] str1		A non-buffered byte string.
 * @param[in] str2		A buffered byte string.
 * @return A CFX_ByteString object.
 */
inline CFX_ByteString operator + (FX_BSTR str1, const CFX_ByteString& str2) { return CFX_ByteString(str1, str2); }

/*@}*/ 

/**
 * @brief A fixed string buffer holding up to certain number of characters.
 *
 * Operations are protected by buffer limit.
 * Please don't use this class directly, use CFX_StringBufTemplate instead.
 */
class CFX_StringBufBase : public CFX_Object
{
public:
	/**
	 * A Constructor
	 *
	 * @param[in] limit		buffer limit.
	 */
	CFX_StringBufBase(FX_STRSIZE limit) { m_Size = 0; m_Limit = limit; }

	/**
	 * Gets a C-style string pointer to the string buffer.
	 *
	 * @return Returns a C-style string pointer to the buffer.
	 */
	FX_CHAR*	GetPtr() const { return (FX_CHAR*)(this + 1); }
	/**
	 * Gets the length of the string.
	 *
	 * @return The length of the string.
	 */
	FX_STRSIZE	GetSize() const { return m_Size; }

	/**
	 * Set this string to be empty.
	 */
	void		Empty() { m_Size = 0; }

	/**
	 * Copy from a non-buffered byte string.
	 *
	 * @param[in] str	A no-buffered byte string.
	 */
	void		Copy(FX_BSTR str);

	/**
	 * Append a non-buffered byte string.
	 *
	 * @param[in] str	A non-buffered byte string.
	 */
	void		Append(FX_BSTR str);

	/**
	 * Append an integer. See FXFORMAT_xxx for flags.
	 *
	 * @param[in] i			The input integer.
	 * @param[in] flags		The formating flags.
	 *
	 * @see CFX_ByteString::FormatInteger
	 */
	void		Append(int i, FX_DWORD flags = 0);

	/**
	 * Gets a non-buffered byte string.
	 *
	 * @return A non-buffered byte string.
	 */
	CFX_ByteStringC		GetStringC() const { return CFX_ByteStringC((FX_CHAR*)(this + 1), m_Size); }
	/**
	 * Get a buffered byte string.
	 *
	 * @return A buffered byte string.
	 */
	CFX_ByteString		GetString() const { return CFX_ByteString((FX_CHAR*)(this + 1), m_Size); }

protected:
	/** the buffer limit. */
	FX_STRSIZE	m_Limit;
	/** the string size. */
	FX_STRSIZE	m_Size;
	// the real buffer follows
};

/**
 * @brief A fixed string buffer template.
 */
template<FX_STRSIZE limit> 
class CFX_StringBufTemplate : public CFX_StringBufBase
{
public:
	/**
	 * A constructor.
	 */
	CFX_StringBufTemplate() : CFX_StringBufBase(limit) {}

	/**
	 * The fixed string buffer.
	 *
	 * @note IMPORTANT: the string is NOT zero terminated. 
	 */
	FX_CHAR		m_Buffer[limit];
};

/** @brief A fixed 256-byte string buffer. */
typedef CFX_StringBufTemplate<256> CFX_StringBuf256;

//*****************************************************************************
//* CFX_WideStringC - constant wide string
//*****************************************************************************
/**
 * @brief CONSTANT WIDE STRING CLASS
 *
 * Constant wide string, it contains no buffer so its content can't be changed directly.
 */
class CFX_WideStringC : public CFX_Object
{
public:
	/**
	 * Constructs a null constant string.
	 */
	CFX_WideStringC()
	{
		m_Ptr = NULL;
		m_Length = 0;
	}
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifndef _NO_LPCSTR_SUPPORT_
//<<<+++OPENSOURCE_MUST_END
	/**
	 * Construct from a character string.
	 *
	 * @param[in] ptr	Pointer to a constant character string, the string must be null-terminated.
	 */
	CFX_WideStringC(FX_LPCWSTR ptr)
	{
		m_Ptr = ptr;
		m_Length = ptr ? (FX_STRSIZE)FXSYS_wcslen(ptr) : 0;
	}
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#endif
//<<<+++OPENSOURCE_MUST_END
	/**
	 * Construct from a single character.
	 *
	 * @param[in] ch	A single character.
	 */
	CFX_WideStringC(FX_WCHAR& ch)
	{
		m_Ptr = &ch;
		m_Length = 1;
	}
	/**
	 * Construct from a character string.
	 *
	 * len can be -1 for null-terminated string.
	 * @param[in] ptr	Pointer to a constant character string.
	 * @param[in] len	The length of the character string. 
	 */
	CFX_WideStringC(FX_LPCWSTR ptr, FX_STRSIZE len)
	{
		m_Ptr = ptr;
		if (len == -1)
			m_Length = (FX_STRSIZE)FXSYS_wcslen(ptr);
		else
			m_Length = len;
	}
	/**
	 * Copy constructor
	 * 
	 * @param[in] src	constant ref to a CFX_WideStringC object.
	 */
	CFX_WideStringC(const CFX_WideStringC& src)
	{
		m_Ptr = src.m_Ptr;
		m_Length = src.m_Length;
	}
	/**
	 * Construct from a wide string.
	 * 
	 * @param[in] src	constant ref to a CFX_ByteString object.
	 */
	CFX_WideStringC(const CFX_WideString& src);

	/**
	 * assignment(=) operator overload. From a character string.
	 *
	 * @param[in] src	Pointer to a constant character string.
	 */
	CFX_WideStringC& operator = (FX_LPCWSTR src)
	{
		m_Ptr = src;
		m_Length = (FX_STRSIZE)FXSYS_wcslen(src);
		return *this;
	}
	/**
	 * assignment(=) operator overload. From a CFX_WideStringC object.
	 *
	 * @param[in] src	constant ref to a CFX_ByteStringC object.
	 */
	CFX_WideStringC& operator = (const CFX_WideStringC& src)
	{
		m_Ptr = src.m_Ptr;
		m_Length = src.m_Length;
		return *this;
	}
	/**
	 * assignment(=) operator overload. From a CFX_ByteString object.
	 *
	 * @param[in] src	constant ref to a CFX_ByteString object.
	 */
	CFX_WideStringC& operator = (const CFX_WideString& src);

	/**
	 * comparison(==) operator overload. case-sensitive.
	 *
	 * @param[in] str	constant ref to a CFX_ByteStringC object.
	 * @return true means equal, otherwise not equal.
	 */
	bool			operator == (const CFX_WideStringC& str) const
	{
		return 	str.m_Length == m_Length && FXSYS_memcmp32(str.m_Ptr, m_Ptr, m_Length*sizeof(FX_WCHAR)) == 0;
	}
	/**
	 * comparison(!=) operator overload. case-sensitive.
	 *
	 * @param[in] str	constant ref to a CFX_WideStringC object.
	 * @return true means not equal, otherwise equal.
	 */
	bool			operator != (const CFX_WideStringC& str) const
	{
		return 	str.m_Length != m_Length || FXSYS_memcmp32(str.m_Ptr, m_Ptr, m_Length*sizeof(FX_WCHAR)) != 0;
	}

	/**
	 * Returns a constant wide string pointer to the wide string.
	 *
	 * @return A constant wide string pointer to the wide string.
	 */
	FX_LPCWSTR		GetPtr() const { return m_Ptr; }
	/**
	 * Returns The length of the byte string.
	 *
	 * @return The length of the byte string.
	 */
	FX_STRSIZE		GetLength() const { return m_Length; }
	/**
	 * This method determines whether a CFX_WideStringC object is empty.
	 *
	 * @return true means empty, otherwise not empty.
	 */
	bool			IsEmpty() const { return m_Length == 0; }

	/**
	 * This method retrieves a single byte specified by an index number.
	 *
	 * @param[in] index		Specifies the zero-based index in the byte string.
	 * @return A single byte.
	 */
	FX_WCHAR		GetAt(FX_STRSIZE index) const { return m_Ptr[index]; }

	/**
	 * This method extracts the first (leftmost) count wide characters from this CFX_WideStringC object as a sub-string. 
	 *
	 * @param[in] count		The count of wide characters expected to extract for the sub-string.
	 * @return A CFX_WideStringC sub-string.
	 */
	CFX_WideStringC	Left(FX_STRSIZE count) const
	{
		if (count < 1) return CFX_WideStringC();
		if (count > m_Length) count = m_Length;
		return CFX_WideStringC(m_Ptr, count);
	}

	/**
	 * This method extracts a substring of length count bytes from this CFX_WideStringC object,
	 * starting at position index (zero-based).
	 *
	 * @param[in] index		Specifies the zero-based index in the CFX_WideStringC object.
	 * @param[in] count		Specifies the number of bytes to extract from this CFX_WideStringC object.
	 * @return A CFX_WideStringC object refer to the substring.
	 */
	CFX_WideStringC	Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const
	{
		if (index < 0) index = 0;
		if (index > m_Length) return CFX_WideStringC();
		if (count < 0 || count > m_Length - index) count = m_Length - index;
		return CFX_WideStringC(m_Ptr + index, count);
	}

	/**
	 * This method extracts the last (rightmost) count wide characters from this CFX_WideStringC object as a sub-string. 
	 *
	 * @param[in] count		The count of wide characters expected to extract for the sub-string.
	 * @return A CFX_WideStringC sub-string.
	 */
	CFX_WideStringC	Right(FX_STRSIZE count) const
	{
		if (count < 1) return CFX_WideStringC();
		if (count > m_Length) count = m_Length;
		return CFX_WideStringC(m_Ptr + m_Length - count, count);
	}

protected:
	/** The constant byte string pointer. */
	FX_LPCWSTR		m_Ptr;
	/** the length in bytes of the byte string. */
	FX_STRSIZE		m_Length;

private:
	/**
	 * new operator forbidden. Cannot allocate a CFX_WideStringC in heap.
	 */
	void*			operator new (size_t) throw() { return NULL; }
};

/** @brief A ref to a constant CFX_WideStringC object. */
typedef const CFX_WideStringC&	FX_WSTR;

/**
 * @brief All application should use the following macro when specifying a wide string constant.
 * "wstr" must be a wide string constant.
 *
 * For example:
 * @code
 *		FX_WSTRC(L"abc").
 * @endcode
 */
#define FX_WSTRC(wstr) CFX_WideStringC((FX_LPCWSTR)wstr, sizeof(wstr) / sizeof(FX_WCHAR) - 1)

//*****************************************************************************
//* CFX_WideString - wide string
//*****************************************************************************
/** @brief This class represents the data of a wide string object. */
struct CFX_StringDataW
{
	/** reference count. */
	long		m_nRefs;
	/** length of data (excluding terminator). */
	FX_STRSIZE	m_nDataLength;
	/** length of allocation. */
	FX_STRSIZE	m_nAllocLength;
	/** real data (actually a variable-sized array). */
	FX_WCHAR	m_String[1];
};

/**
 * @brief WIDE STRING CLASS
 * 
 * On Windows platforms, a wide string is represented by UTF-16LE encoding;
 * On Unix/Linux platforms, a wide string is represented by UCS-4 encoding.
 */
class CFX_WideString : public CFX_Object
{
public:
	/**
	 * Construct a null wide string.
	 */
	CFX_WideString() { m_pData = NULL; }
	/**
	 * Copy constructor.
	 *
	 * @param[in] str	A constant ref to a CFX_WideString object.
	 */
	CFX_WideString(const CFX_WideString& str);
	/**
	 * Construct from a wide character string.
	 *
	 * @param[in] ptr	Pointer to a constant wide character string.
	 * @param[in] len	The length of the wide character string. len can be -1 for zero terminated wide character string.
	 */
	CFX_WideString(FX_LPCWSTR ptr, FX_STRSIZE len = -1) { InitStr(ptr, len); }

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * Construct from a native wide character string.
	 * 
	 * @param[in] str	Pointer to a constant wide character string.
	 * @param[in] len	The length of the wide character string. len can be -1 for zero terminated wide character string.
	 */
	CFX_WideString(const wchar_t* ptr, FX_STRSIZE len = -1) { InitStr((FX_LPCWSTR)ptr, len); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * Construct from a single wide character.
	 *
	 * @param[in] ch	A single wide character.
	 */
	CFX_WideString(FX_WCHAR ch);
	/**
	 * Construct from a constant ref to a CFX_WideStringC object.
	 *
	 * @param[in] str		A constant ref to a CFX_WideStringC object.
	 */
	CFX_WideString(const CFX_WideStringC& str);
	/**
	 * Concatenate constructor.
	 *
	 * @param[in] str1		Fist constant ref to a CFX_WideStringC object.
	 * @param[in] str2		Second constant ref to a CFX_WideStringC object.
	 */
	CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2);
	/**
	 * The Destructor.
	 */
	~CFX_WideString();

	/**
	 * Create a wide string from system multi-byte charset.
	 *
	 * @param[in] str	a multi-byte charset string. 
	 * @param[in] len	The length in bytes of the multi-byte charset string. len can be -1 for zero terminated multi-byte charset string.
	 * @return A wide string.
	 */
	static CFX_WideString	FromLocal(const char* str, FX_STRSIZE len = -1);
	/**
	 * Create a wide string from UTF-8 string (ASCII string compatible).
	 *
	 * @param[in] str	A UTF8 string.
	 * @param[in] len	The length in bytes of the UTF8 string. len can be -1 for zero terminated UTF8 string.
	 * @return A wide string.
	 */
	static CFX_WideString	FromUTF8(const char* str, FX_STRSIZE len = -1);
	/**
	 * Create a wide string from UTF16LE encoded string.
	 * 
	 * @note len is number of bytes.
	 *
	 * @param[in] str	A UTF16LE encoded string.
	 * @param[in] len	The length in bytes of the UTF16LE encoded string. len can be -1 for zero terminated UTF16LE string.
	 * @return A wide string.
	 */
	static CFX_WideString	FromUTF16LE(const unsigned short* str, FX_STRSIZE len = -1);

	/**
	 * FX_LPCWSTR type conversion operator.
	 */
	operator FX_LPCWSTR() const { return m_pData ? m_pData->m_String : (FX_WCHAR*)L""; }

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * const wchar_t* type conversion operator.
	 */
	operator const wchar_t*() const { return m_pData ? (const wchar_t*)m_pData->m_String : L""; }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * Set this string to be empty.
	 */
	void					Empty();
	/**
	 * This method determines whether a CFX_WideString object is empty.
	 *
	 * @return 0 means not empty, otherwise empty.
	 */	
	FX_BOOL					IsEmpty() const { return !GetLength(); }

	/**
	 * Returns number of characters, not bytes. Trailing zero not counted.
	 * 
	 * @return The number of characters.
	 */
	FX_STRSIZE				GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; }

	/**
	 * assignment(=) operator overload. From a wide character string.
	 *
	 * @param[in] str		The wide character string.
	 */
	const CFX_WideString&	operator = (FX_LPCWSTR str);

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * assignment(=) operator overload. From a native wide character string.
	 *
	 * @param[in] str		The native wide character string.
	 */
	const CFX_WideString&	operator = (const wchar_t* str) { return operator = ((FX_LPCWSTR)str); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * assignment(=) operator overload. From a wide string.
	 *
	 * @param[in] stringSrc The Input wide string.
	 */
	const CFX_WideString&	operator =(const CFX_WideString& stringSrc);
	/**
	 * assignment(=) operator overload. From a const wide string.
	 *
	 * @param[in] stringSrc The Input wide string.
	 */
	const CFX_WideString&	operator =(const CFX_WideStringC& stringSrc);

	/**
	 * Concatenation(+=) operator overload. Concatenate a wide character string.
	 *
	 * @param[in] str		The wide character string. 
	 */
	const CFX_WideString&	operator += (FX_LPCWSTR str);

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * Concatenation(+=) operator overload. Concatenate a native wide character string.
	 *
	 * @param[in] str		The native wide character string.
	 */
	const CFX_WideString&	operator += (const wchar_t* str) { return operator += ((FX_LPCWSTR)str); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * Concatenation(+=) operator overload. Concatenate a single wide character.
	 *
	 * @param[in] ch		The single wide character.
	 */
	const CFX_WideString&	operator += (FX_WCHAR ch);
	/**
	 * Concatenation(+=) operator overload. Concatenate a wide string.
	 *
	 * @param[in] str		The input wide string.
	 */
	const CFX_WideString&	operator += (const CFX_WideString& str);
	/**
	 * Concatenation(+=) operator overload. Concatenate a constant wide string.
	 *
	 * @param[in] str		The input wide string.
	 */
	const CFX_WideString&	operator += (const CFX_WideStringC& str);

	/**
	 * This method retrieves a single wide character specified by an index number.
	 *
	 * @param[in] nIndex	Specifies the zero-based index in the wide string.
	 * @return A single wide character.
	 */
	FX_WCHAR				GetAt(FX_STRSIZE nIndex) const { return m_pData ? m_pData->m_String[nIndex] : 0; }
	/**
	 * Subscript([]) operator overload. It retrieves a wide character specified by the zero-based index in nIndex.
	 *
	 * @param[in] nIndex	Specifies the zero-based index in the wide string.
	 * @return A single wide character.
	 */
	FX_WCHAR				operator[](FX_STRSIZE nIndex) const { return m_pData ? m_pData->m_String[nIndex] : 0; }
	/**
	 * This method overwrites a single wide character specified by an index number.
	 *
	 * @param[in] nIndex	Specifies the zero-based index in the wide string.
	 * @param[in] ch		a single wide character.
	 */
	void					SetAt(FX_STRSIZE nIndex, FX_WCHAR ch);

	/**
	 * Compare the the string with a wide character string. case-sensitive.
	 * 
	 * Return -1 if this string is "smaller" (in alphabetic order) than the other,
	 * 0 for equal, 1 for larger in alphabetic order.
	 *
	 * @param[in] str		The wide character string to be compared.
	 * @retval -1	smaller
	 * @retval 0	equal
	 * @retval 1	larger
	 */
	int						Compare(FX_LPCWSTR str) const;
	/**
	 * Compare the the string with another. case-sensitive.
	 * 
	 * Return -1 if this string is "smaller" (in alphabetic order) than the other,
	 * 0 for equal, 1 for larger in alphabetic order.
	 *
	 * @param[in] str		The wide string to be compared.
	 * @retval -1	smaller
	 * @retval 0	equal
	 * @retval 1	larger
	 */
	int						Compare(const CFX_WideString& str) const;

	/**
	 * Compare the the string with a wide character string. case-insensitive.
	 * 
	 * Return -1 if this string is "smaller" (in alphabetic order) than the other,
	 * 0 for equal, 1 for larger in alphabetic order.
	 *
	 * @param[in] str		The wide character string to be compared.
	 * @retval -1	smaller
	 * @retval 0	equal
	 * @retval 1	larger
	 */
	int						CompareNoCase(FX_LPCWSTR str) const;

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * Compare the the string with a native wide character string. case-insensitive.
	 * 
	 * Return -1 if this string is "smaller" (in alphabetic order) than the other,
	 * 0 for equal, 1 for larger in alphabetic order.
	 *
	 * @param[in] str		The native wide character string to be compared.
	 * @retval -1	smaller
	 * @retval 0	equal
	 * @retval 1	larger
	 */
	int						CompareNoCase(const wchar_t* str) const { return CompareNoCase((FX_LPCWSTR)str); }
	/**
	 * Compare the the string with another. case-insensitive.
	 * 
	 * Return -1 if this string is "smaller" (in alphabetic order) than the other,
	 * 0 for equal, 1 for larger in alphabetic order.
	 *
	 * @param[in] str		The wide string to be compared.
	 * @retval -1	smaller
	 * @retval 0	equal
	 * @retval 1	larger
	 */
	int						CompareNoCase(const CFX_WideString& str) const { return CompareNoCase((FX_LPCWSTR)str); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * Check if this string equals to another. It's faster than Compare if you just want to check
	 * whether two strings equal.
	 *
	 * @param[in] str	The wide string to be compared.
	 * @return true means equal, otherwise not equal.
	 */
	bool					Equal(const CFX_WideStringC& str) const;

	/**
	 * This method extracts a substring from this CFX_WideString object,
	 * starting at position nFirst (zero-based) to last. 
	 *
	 * @param[in] first		Specifies the zero-based index of the starting position in this CFX_WideString object.
	 * @return A CFX_WideString sub-string.
	 */
	CFX_WideString			Mid(FX_STRSIZE first) const;
	/**
	 * This method extracts a substring of count wide character from this CFX_WideString object,
	 * starting at position nFirst (zero-based) to last. 
	 *
	 * @param[in] first		Specifies the zero-based index of the starting position in this CFX_WideString object.
	 * @param[in] count		The count of wide characters expected to extract for the sub-string.
	 * @return A CFX_WideString sub-string.
	 */
	CFX_WideString			Mid(FX_STRSIZE first, FX_STRSIZE count) const;
	/**
	 * This method extracts the first (leftmost) count wide characters from this CFX_WideString object as a sub-string. 
	 *
	 * @param[in] count		The count of wide characters expected to extract for the sub-string.
	 * @return A CFX_WideString sub-string.
	 */
	CFX_WideString			Left(FX_STRSIZE count) const;
	/**
	 * This method extracts the last (rightmost) count wide characters from this CFX_WideString object as a sub-string. 
	 *
	 * @param[in] count		The count of wide characters expected to extract for the sub-string.
	 * @return A CFX_WideString sub-string.
	 */
	CFX_WideString			Right(FX_STRSIZE count) const;

	/**
	 * Insert a wide character before specific position.
	 *
	 * @param[in] index		Specifies the zero-based index in the wide string.
	 * @param[in] ch		A single wide character.
	 * @return The new length of the wide string.
	 */
	FX_STRSIZE				Insert(FX_STRSIZE index, FX_WCHAR ch);
	/**
	 * Delete one or more wide characters starting from specific position.
	 * 
	 * @param[in] index		Specifies the zero-based index in the wide string for starting deleting.
	 * @param[in] count		Count of wide characters to be deleted.
	 * @return The new length of the wide string.
	 */
	FX_STRSIZE				Delete(FX_STRSIZE index, FX_STRSIZE count = 1);

	/**
	 * Format a number of parameters into this wide string.
	 * 
	 * @param[in] lpszFormat	Specifies a format-control string.
	 */
	void					Format(FX_LPCWSTR lpszFormat, ... );
	/**
	 * Format a number of parameters into this wide string. using va_list.
	 *
	 * @param[in] lpszFormat	Specifies a format-control string.
	 * @param[in] argList		Variable-argument lists.
	 * @see CFX_WideString::Format
	 */
	void					FormatV(FX_LPCWSTR lpszFormat, va_list argList);

	/**
	 * Change case of English letters to lower.
	 */
	void					MakeLower();
	/**
	 * Change case of English letters to upper.
	 */
	void					MakeUpper();

	/**
	 * Trim white spaces from the right side of the wide string.
	 */
	void					TrimRight();
	/**
	 * Trim continuous occurrences of specified character from right side of the wide string.
	 * 
	 * @param[in] chTarget		The specified character.
	 */
	void					TrimRight(FX_WCHAR chTarget);
	/**
	 * Trim continuous occurrences of specified characters from right side of the wide string.
	 *
	 * @param[in] lpszTargets	The specified characters.
	 */
	void					TrimRight(FX_LPCWSTR lpszTargets);

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * Trim continuous occurrences of specified characters from right side of the wide string.
	 *
	 * @param[in] lpszTargets	The specified characters.
	 */
	void					TrimRight(const wchar_t* lpszTargets) { TrimRight((FX_LPCWSTR)lpszTargets); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * Trim white spaces from the left side of the wide string.
	 */
	void					TrimLeft();
	/**
	 * Trim continuous occurrences of specified character from left side of the wide string.
	 * 
	 * @param[in] chTarget		The specified character.
	 */
	void					TrimLeft(FX_WCHAR chTarget);
	/**
	 * Trim continuous occurrences of specified characters from left side of the wide string.
	 *
	 * @param[in] lpszTargets	The specified characters.
	 */
	void					TrimLeft(FX_LPCWSTR lpszTargets);

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * Trim continuous occurrences of specified characters from left side of the wide string.
	 *
	 * @param[in] lpszTargets	The specified characters.
	 */
	void					TrimLeft(const wchar_t* lpszTargets) { TrimLeft((FX_LPCWSTR)lpszTargets); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * Reserve a buffer that can hold specific number of characters.
	 *
	 * @param[in] len		the Length expected to reserve.
	 *
	 * @see CFX_ByteString::Reserve(FX_STRSIZE)
	 */
	void					Reserve(FX_STRSIZE len);
	/**
	 * Get a buffer with specific number of characters allocated.
	 *
	 * @param[in] len		the Length expected to get.
	 * @return A wide character string pointer to the wide string.
	 */
	FX_LPWSTR				GetBuffer(FX_STRSIZE len);
	/**
	 * Lock and get the current string buffer, so the caller can modify the returned buffer.
	 * Caller can modified the returned buffer, and should call ReleaseBuffer() after modification done.
	 *
	 * @return A wide character string pointer to the wide string.
	 */
	FX_LPWSTR				LockBuffer();
	/**
	 * Release the buffer fetched by GetBuffer() or LockBuffer, and set the length of modified string.
	 *
	 * If len parameter is -1, then it's assumed to be a zero-terminated string.
	 *
	 * @param[in] len		the Length expected to release to.
	 */
	void					ReleaseBuffer(FX_STRSIZE len = -1);

	/**
	 * Convert to other data type.
	 *
	 * @return A decimal number.
	 */
	int						GetInteger() const;

	/**
	 * Convert to other data type.
	 *
	 * @return A floating point number.
	 */
	FX_FLOAT				GetFloat() const;

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
	/**
	 * Find a sub-string, from specific position. Only first occurrence is found.
	 *
	 * @param[in] lpszSub	The sub-string to be found.
	 * @param[in] start		Specifies the zero-based index of the starting position to do finding.
	 * @retval -1 Not found.
	 * @retval other Specifies position in the string.
	 */
	FX_STRSIZE				Find(const wchar_t* lpszSub, FX_STRSIZE start=0) const { return Find((FX_LPCWSTR)lpszSub, start); }
	/**
	 * Find a sub-string, from specific position. Only first occurrence is found.
	 *
	 * @param[in] lpszSub	The sub-string to be found.
	 * @param[in] start		Specifies the zero-based index of the starting position to do finding.
	 * @retval -1 Not found.
	 * @retval other Specifies position in the string.
	 */
	FX_STRSIZE				Find(CFX_WideString& lpszSub, FX_STRSIZE start=0) const { return Find((FX_LPCWSTR)lpszSub, start); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

	/**
	 * Find a sub-string, from specific position. Only first occurrence is found.
	 *
	 * @param[in] lpszSub	The sub-string to be found.
	 * @param[in] start		Specifies the zero-based index of the starting position to do finding.
	 * @retval -1 Not found.
	 * @retval other Specifies position in the string.
	 */
	FX_STRSIZE				Find(FX_LPCWSTR lpszSub, FX_STRSIZE start=0) const;
	/**
	 * Find a character, from specific position. Only first occurrence is found.
	 *
	 * @param[in] ch		The character to be found.
	 * @param[in] start		Specifies the zero-based index of the starting position to do finding.
	 * @retval -1 Not found.
	 * @retval other Specifies position in the string.
	 */
	FX_STRSIZE				Find(FX_WCHAR ch, FX_STRSIZE start=0) const;

	/**
	 * Replace all patterns in the string with a new sub-string.
	 *
	 * @param[in] lpszOld		Specified the string to be matched and replaced in the wide string.
	 * @param[in] lpszNew		Specified the string to replace.
	 * @return The number of replaced patterns.
	 */
	FX_STRSIZE				Replace(FX_LPCWSTR lpszOld, FX_LPCWSTR lpszNew);
	/**
	 * Remove all occurrence of a particular character.
	 * 
	 * @param[in] ch	Specified the character to be removed.
	 * @return The number of characters removed.
	 */
	FX_STRSIZE				Remove(FX_WCHAR ch);

	/**
	 * Do UTF8 encoding.
	 *
	 * @return A byte string.
	 */
	CFX_ByteString			UTF8Encode() const;
	/**
	 * Do UTF16LE encoding.
	 *
	 * Get UTF-16LE encoded memory block. 
	 *
	 * @return A byte string.
	 */
	CFX_ByteString			UTF16LE_Encode(FX_BOOL bTerminate = TRUE) const;

	/**
	 * Load MBCS data into this wide string, using specified character mapper.
	 * If no character mapper specified, the system default mapper will be used.
	 *
	 * @param[in] str		A byte string.
	 * @param[in] pCharMap	A character mapper.
	 */
	void					ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap = NULL);

protected:
	void					InitStr(FX_LPCWSTR ptr, int len); 

	/** Pointer to ref counted wide string data. */
	CFX_StringDataW*		m_pData;

	void					CopyBeforeWrite();
	void					AllocBeforeWrite(FX_STRSIZE nLen);

	void					ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
	void					ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCWSTR lpszSrc1Data, FX_STRSIZE nSrc2Len, FX_LPCWSTR lpszSrc2Data);
	void					AssignCopy(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
	void					AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex, FX_STRSIZE nExtraLen) const;
};

inline CFX_WideStringC::CFX_WideStringC(const CFX_WideString& src)
{
	m_Ptr = (FX_LPCWSTR)src;
	m_Length = src.GetLength();
}

inline CFX_WideStringC& CFX_WideStringC::operator = (const CFX_WideString& src)
{
	m_Ptr = (FX_LPCWSTR)src;
	m_Length = src.GetLength();
	return *this;
}

/**
 * @name Wide string concatenation operation
 * Both side of the concatenation operator (+) can be:
 * - A buffered wide string (const CFX_WideString&);
 * - A non-buffered wide string (const CFX_WideStringC&);
 * - A zero-terminated C-style wide string (FX_LPCWSTR);
 * - A single character (FX_WCHAR);
 * But you must have at least one CFX_WideString or CFX_WideStringC on one side.
 */
 /*@{*/

/**
 * Concatenate a non-buffered wide string and a non-buffered wide string.
 *
 * @param[in] str1		A non-buffered wide string.
 * @param[in] str2		A non-buffered wide string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (const CFX_WideStringC& str1, const CFX_WideStringC& str2) { return CFX_WideString(str1, str2); }
#ifndef _NO_LPCSTR_SUPPORT_
/**
 * Concatenate a non-buffered byte string and a zero-terminated C-style string
 *
 * @param[in] str1		A non-buffered wide string.
 * @param[in] str2		A zero-terminated C-style string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (const CFX_WideStringC& str1, FX_LPCWSTR str2) { return CFX_WideString(str1, str2); }
/**
 * Concatenate a zero-terminated C-style string and a non-buffered byte string. 
 *
 * @param[in] str1		A zero-terminated C-style string.
 * @param[in] str2		A non-buffered wide string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (FX_LPCWSTR str1,const CFX_WideStringC& str2) { return CFX_WideString(str1, str2); }
#endif
/**
 * Concatenate a non-buffered byte string and a single character or byte. 
 *
 * @param[in] str1		A non-buffered wide string.
 * @param[in] ch		A single character.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (const CFX_WideStringC& str1, FX_WCHAR ch) { return CFX_WideString(str1, CFX_WideStringC(ch)); }
/**
 * Concatenate a single character or byte and a non-buffered byte string. 
 *
 * @param[in] ch		A single character.
 * @param[in] str2		A non-buffered wide string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (FX_WCHAR ch, const CFX_WideStringC& str2) { return CFX_WideString(ch, str2); }

/**
 * Concatenate a buffered byte string and a buffered byte string. 
 *
 * @param[in] str1		A buffered wide string.
 * @param[in] str2		A buffered wide string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (const CFX_WideString& str1, const CFX_WideString& str2) { return CFX_WideString(str1, str2); }
/**
 * Concatenate a buffered byte string and a single character or byte. 
 *
 * @param[in] str1		A buffered wide string.
 * @param[in] ch		A single character.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (const CFX_WideString& str1, FX_WCHAR ch) { return CFX_WideString(str1, CFX_WideStringC(ch)); }
/**
 * Concatenate a single character or byte and a buffered byte string. 
 *
 * @param[in] ch		A single character.
 * @param[in] str2		A buffered wide string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (FX_WCHAR ch, const CFX_WideString& str2) { return CFX_WideString(ch, str2); }
#ifndef _NO_LPCSTR_SUPPORT_
/**
 * Concatenate a buffered wide string and a zero-terminated C-style string. 
 *
 * @param[in] str1		A buffered wide string.
 * @param[in] str2		A zero-terminated C-style string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (const CFX_WideString& str1, FX_LPCWSTR str2) { return CFX_WideString(str1, str2); }
/**
 * Concatenate a zero-terminated C-style string and a buffered byte string. 
 *
 * @param[in] str1		A zero-terminated C-style string.
 * @param[in] str2		A buffered wide string.
 * @return A CFX_ByteString object.
 */
inline CFX_WideString operator + (FX_LPCWSTR str1, const CFX_WideString& str2) { return CFX_WideString(str1, str2); }
#endif
/**
 * Concatenate a buffered byte string and a non-buffered byte string. 
 *
 * @param[in] str1		A buffered wide string.
 * @param[in] str2		A non-buffered wide string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (const CFX_WideString& str1, const CFX_WideStringC& str2) { return CFX_WideString(str1, str2); }
/**
 * Concatenate a non-buffered byte string and a buffered byte string. 
 *
 * @param[in] str1		A non-buffered wide string.
 * @param[in] str2		A buffered wide string.
 * @return A CFX_WideString object.
 */
inline CFX_WideString operator + (const CFX_WideStringC& str1, const CFX_WideString& str2) { return CFX_WideString(str1, str2); }

/*@}*/ 

/**
 * @name Wide string compare operation
 */
 /*@{*/

/**
 * comparison(==) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second wide string.
 * @return true means equal, otherwise not equal.
 */
bool operator==(const CFX_WideString& s1, const CFX_WideString& s2);
/**
 * comparison(==) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second wide string.
 * @return true means equal, otherwise not equal.
 */
bool operator==(const CFX_WideString& s1, const CFX_WideStringC& s2);
/**
 * comparison(==) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second wide string.
 * @return true means equal, otherwise not equal.
 */
bool operator==(const CFX_WideStringC& s1, const CFX_WideString& s2);
/**
 * comparison(==) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second wide character string.
 * @return true means equal, otherwise not equal.
 */
bool operator== (const CFX_WideString& s1, FX_LPCWSTR s2);
/**
 * comparison(==) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide character string.
 * @param[in] s2	The second wide string.
 * @return true means equal, otherwise not equal.
 */
bool operator==(FX_LPCWSTR s1, const CFX_WideString& s2);

/**
 * comparison(!=) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second wide string.
 * @return true means not equal, otherwise equal.
 */
bool operator!=(const CFX_WideString& s1, const CFX_WideString& s2);
/**
 * comparison(!=) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second wide string.
 * @return true means not equal, otherwise equal.
 */
bool operator!=(const CFX_WideString& s1, const CFX_WideStringC& s2);
/**
 * comparison(!=) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second wide string.
 * @return true means not equal, otherwise equal.
 */
bool operator!=(const CFX_WideStringC& s1, const CFX_WideString& s2);
/**
 * comparison(!=) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second wide character string.
 * @return true means not equal, otherwise equal.
 */
bool operator!= (const CFX_WideString& s1, FX_LPCWSTR s2);
/**
 * comparison(!=) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide character string.
 * @param[in] s2	The second wide string.
 * @return true means not equal, otherwise equal.
 */
bool operator!=(FX_LPCWSTR s1, const CFX_WideString& s2);

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
#ifdef _NATIVE_WCHAR_T_DEFINED
/**
 * comparison(==) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second native wide character string.
 * @return true means equal, otherwise not equal.
 */
inline bool operator== (const CFX_WideString& s1, const wchar_t* s2) { return operator==(s1, (FX_LPCWSTR)s2); }
/**
 * comparison(==) operator overload. case-sensitive.
 *
 * @param[in] s1	The first native wide character string.
 * @param[in] s2	The second wide string.
 * @return true means equal, otherwise not equal.
 */
inline bool operator==(const wchar_t* s1, const CFX_WideString& s2) { return operator==((FX_LPCWSTR)s1, s2); }
/**
 * comparison(!=) operator overload. case-sensitive.
 *
 * @param[in] s1	The first wide string.
 * @param[in] s2	The second native wide character string.
 * @return true means not equal, otherwise equal.
 */
inline bool operator!= (const CFX_WideString& s1, const wchar_t* s2) { return operator!=(s1, (FX_LPCWSTR)s2); }
/**
 * comparison(!=) operator overload. case-sensitive.
 *
 * @param[in] s1	The first native wide character string.
 * @param[in] s2	The second wide string.
 * @return true means not equal, otherwise equal.
 */
inline bool operator!=(const wchar_t* s1, const CFX_WideString& s2) { return operator!=((FX_LPCWSTR)s1, s2); }
#endif
//<<<+++OPENSOURCE_MUST_END
#endif

/*@}*/ 

/**
 *
 * Convert a non-buffered byte string to a floating-point number.
 *
 * @param[in] str	A non-buffered byte string.
 * @return A floating-point number.
 */
FX_FLOAT FX_atof(FX_BSTR str);
/**
 * Convert a non-buffered byte string to a number.
 *
 * @param[in] str		A non-buffered byte string.
 * @param[out] bInteger	Non-zero values means the string can convert to a number, otherwise can not. 
 * @param[out] pData		It receives the converted number.
 */
void FX_atonum(FX_BSTR str, FX_BOOL& bInteger, void* pData);

/**
 * Convert float to byte string.
 * 
 * @param[in] f		Float number.
 * @param[out] buf	Buffer of float string, buf should have 32 bytes at least.
 * 
 * @return	Length of formatted float string in buf, in bytes.
 */
FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_LPSTR buf);

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
/**
 * @name Basic Unicode character attribute routines
 */
/*@{*/
/** Convert to upper-case letter */
FX_WCHAR	FXWCHAR_GetUpper(FX_WCHAR wchar);
/** Convert to lower-case letter */
FX_WCHAR	FXWCHAR_GetLower(FX_WCHAR wchar);
/** Check if the unicode can break a word */
FX_BOOL		FXWCHAR_IsWordBreak(FX_WCHAR wchar);
/** Check if the unicode is space */
FX_BOOL		FXWCHAR_IsSpace(FX_WCHAR wchar);
/**
 * @name text direction defines
 */
/*@{*/
/** @brief Left to right order */
#define FXWCHAR_LTR			0
/** @brief Right to left order */
#define FXWCHAR_RTL			1
/** @brief Not sure about the order or don't care */
#define FXWCHAR_UNKNOWN		2
/*@}*/ 
/** Get text direction */
int			FXWCHAR_GetDirection(FX_WCHAR wchar);
/*@}*/ 
//<<<+++OPENSOURCE_END
#endif

/**
 * @name Encode wide string into UTF-8 byte string
 */
/*@{*/

/**
 * Encode a wide string into a UTF-8 string.
 *
 * @param[in] pwsStr	points to a wide string buffer.
 * @param[in] len		length of wide string, in wide characters (FX_WCHAR).
 * @return	the object of encoded UTF-8 string.
 */
CFX_ByteString	FX_UTF8Encode(FX_LPCWSTR pwsStr, FX_STRSIZE len);
/**
 * Encode a wide string into a UTF-8 string.
 *
 * @param[in] wsStr		a constant wide string.
 * @return	the object of encoded UTF-8 string.
 */
inline CFX_ByteString	FX_UTF8Encode(FX_WSTR wsStr) {return FX_UTF8Encode(wsStr.GetPtr(), wsStr.GetLength());}
/**
 * Encode a wide string into a UTF-8 string.
 *
 * @param[in] wsStr		a wide string.
 * @return	the object of encoded UTF-8 string.
 */
inline CFX_ByteString	FX_UTF8Encode(const CFX_WideString &wsStr) {return FX_UTF8Encode((FX_LPCWSTR)wsStr, wsStr.GetLength());}

/*@}*/ 
#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
//*****************************************************************************
//* CFX_ByteStringL - long term byte string
//*****************************************************************************
class CFX_ByteStringL : public CFX_ByteStringC
{
public:
	CFX_ByteStringL() : CFX_ByteStringC() {}
	~CFX_ByteStringL() {}
	
	void		Empty(IFX_Allocator* pAllocator);

	FX_LPSTR	AllocBuffer(FX_STRSIZE length, IFX_Allocator* pAllocator);
	
	void		Set(FX_BSTR src, IFX_Allocator* pAllocator);
};

//*****************************************************************************
//* CFX_WideStringL - long term wide string
//*****************************************************************************
class CFX_WideStringL : public CFX_WideStringC
{
public:
	CFX_WideStringL() : CFX_WideStringC() {}
	~CFX_WideStringL() {}
	
	void		Empty(IFX_Allocator* pAllocator);

	void		Set(FX_WSTR src, IFX_Allocator* pAllocator);
	
	int			GetInteger() const;
	FX_FLOAT	GetFloat() const;
	
	void		TrimRight(FX_LPCWSTR lpszTargets);
};

void	FX_UTF8Encode(FX_LPCWSTR pwsStr, FX_STRSIZE len, CFX_ByteStringL &utf8Str, IFX_Allocator* pAllocator = NULL);
//<<<+++OPENSOURCE_END
#endif

//<<<+++OPENSOURCE_MUST_BEGIN
#endif		// _FX_STRING_H_
//<<<+++OPENSOURCE_MUST_END

/** @} */

//<<<+++OPENSOURCE_END
